package main

import (
	"bufio"
	"fmt"
	"io"
	"io/ioutil"
	"os"
)

// file.Read 读取文件
func fileRead() {
	file, err := os.Open("./file_operation.go") // 找当前文件不能用 go run 命令，需要build后执行 可执行文件
	if err != nil {
		fmt.Printf("open file failed!,err:%v\n", err)
		return
	}
	defer file.Close()
	var tmp = make([]byte, 128) // 声明读取内容的字节切片 容量为128
	var content []byte
	for { // 循环读取文件内容
		n, err := file.Read(tmp) // 读取文件内容
		if err == io.EOF {
			fmt.Println("文件读完了")
			break
		}
		if err != nil {
			fmt.Printf("read file failed,err:%v\n", err)
			return
		}
		content = append(content, tmp[:n]...)
	}
	fmt.Println(string(content)) // 将byte转成string
}

// bufio 读取文件
func fileReadByBufio() {
	file, err := os.Open("./file_operation.go")
	if err != nil {
		fmt.Printf("open file failed,err:%v\n", err)
		return
	}
	defer file.Close()
	// 创建bufio读取文件流
	reader := bufio.NewReader(file)
	for {
		line, err := reader.ReadString('\n') // 注意是字符，返回当前行及错误信息
		if err == io.EOF {
			fmt.Println("文件读取完了")
			break
		}
		if err != nil {
			fmt.Printf("read file failed,err:%v\n", err)
			return
		}
		fmt.Print(line) // 打印读取的当前行信息
	}
}

// ioutil 读取文件
func fileReadByIoutil() {
	content, err := ioutil.ReadFile("./file_operation.go")
	if err != nil {
		fmt.Printf("read file failed,err:%v\n", err)
		return
	}
	fmt.Print(string(content))
}

// Write/WriteString 文件写入
func fileWrite() {
	file, err := os.OpenFile("xx.txt", os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0666) // 打开文件xx.txt 没有则创建，存在则追加文件内容
	if err != nil {
		fmt.Printf("openfile failed,err:%v\n", err)
		return
	}
	defer file.Close()
	str := "hello world!"
	file.Write([]byte(str))
	file.WriteString("welcome to")
}

// bufio 写入文件
func fileWriteByBufio() {
	file, err := os.OpenFile("xx.txt", os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0666) // 打开文件xx.txt 没有则创建，存在则追加文件内容
	if err != nil {
		fmt.Printf("openfile failed,err:%v\n", err)
		return
	}
	defer file.Close()
	// 创建文件写入流
	writer := bufio.NewWriter(file)
	for i := 0; i < 10; i++ {
		writer.WriteString("哈哈哈哈！\n") //将数据先写入缓存
	}
	writer.Flush() // 把缓存中的内容写入文件
}

// ioutil 写入文件
func fileWriteByIoutil() {
	str := "加油奥利给"
	err := ioutil.WriteFile("xx.txt", []byte(str), 0666)
	if err != nil {
		fmt.Printf("write file failed,err:%v\n", err)
		return
	}
}

// copyFile
func copyFile(distName, srcName string) (written int64, err error) {
	// 以读的方式打开源文件
	src, err := os.Open(srcName)
	if err != nil {
		fmt.Printf("open file %s failed,err:%v\n", srcName, err)
		return
	}
	defer src.Close()
	// 以写的方式打开目标文件
	dist, err := os.OpenFile(distName, os.O_CREATE|os.O_WRONLY, 0644)
	if err != nil {
		fmt.Printf("open file %s failed,err:%v\n", distName, err)
		return
	}
	defer dist.Close()
	// 通过 io.copy() 方法拷贝内容
	return io.Copy(dist, src)
}

func main() {
	// fileRead()
	// fileReadByBufio()
	// fileReadByIoutil()
	// fileWrite()
	// fileWriteByBufio()
	// fileWriteByIoutil()

	_, err := copyFile("dst.txt", "xx.txt")
	if err != nil {
		fmt.Println("copy file failed,err:", err)
		return
	}
	fmt.Println("copy done!")

}
